home *** CD-ROM | disk | FTP | other *** search
/ CDUTIL 13 / CDUTIL #13 Julio 1995.iso / windows / acadcom / ads / sample / fact.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-08  |  8.4 KB  |  277 lines

  1. /* Next available MSG number is   8 */
  2.  
  3. /*    FACT.C
  4.  
  5.    Copyright (C) 1990, 1991, 1992, 1993, 1994 by Autodesk, Inc.
  6.  
  7.    Permission to use, copy, modify, and distribute this software in 
  8.    object code form for any purpose and without fee is hereby granted, 
  9.    provided that the above copyright notice appears in all copies and 
  10.    that both that copyright notice and the limited warranty and 
  11.    restricted rights notice below appear in all supporting 
  12.    documentation.
  13.  
  14.    AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.  
  15.    AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF 
  16.    MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.  AUTODESK, INC.
  17.    DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE 
  18.    UNINTERRUPTED OR ERROR FREE.
  19.  
  20.    Use, duplication, or disclosure by the U.S. Government is subject to 
  21.    restrictions set forth in FAR 52.227-19 (Commercial Computer 
  22.    Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) 
  23.    (Rights in Technical Data and Computer Software), as applicable.
  24.     
  25.    .
  26.  
  27.       DESCRIPTION:
  28.  
  29.       ADS FACTORIAL application - 3/14/90
  30.       Fancier function tables, and add sqr for illustration - 7/21/90
  31.  
  32. */
  33.  
  34. #include  <stdio.h>
  35. #include  "adslib.h"
  36.  
  37. /* Utility definition to get an  array's  element  count  (at  compile
  38.    time).   For  example:  
  39.  
  40.        int  arr[] = {1,2,3,4,5};
  41.        ... 
  42.        printf("%d", ELEMENTS(arr));
  43.  
  44.    would print a five.  ELEMENTS("abc") can also be used to  tell  how
  45.    many  bytes are in a string constant INCLUDING THE TRAILING NULL. */
  46.  
  47. #define ELEMENTS(array) (sizeof(array)/sizeof((array)[0]))
  48.  
  49.  
  50. /* All the functions that we'll define will be listed in a single table,
  51.    together with the internal function that we call to handle each.  The
  52.    functions all take a single argument (the resbuf that has the
  53.    arguments) and return an integer (RTNORM or RTERROR for good or bad
  54.    status).  */
  55.  
  56.  
  57. /* First, define the structure of the table: a string giving the AutoCAD name
  58.    of the function, and a pointer to a function returning type int. */
  59. struct func_entry { char *func_name; int (*func) _((struct resbuf *)); };
  60.  
  61. /* Here we declare the functions that handle the calls; at the moment there are
  62.    two of them. */
  63. int fact       _((struct resbuf *rb));
  64. int squareroot _((struct resbuf *rb));
  65.  
  66. /* Here we define the array of function names and handlers. */
  67. static struct func_entry func_table[] = { {/*MSG0*/"fact", fact},
  68.                                           {/*MSG0*/"sqr", squareroot},
  69.                                         };
  70. /* To add more functions to this table, just put them in the list, after
  71.    declaring the function names.  Note that in standard C it's all right to
  72.    have a superfluous comma after the last item.  */
  73.  
  74.  
  75. /* The code from here to the end of dofun() is UNCHANGED when you add or delete
  76.    functions. */
  77.  
  78.  
  79. /*  Declarations of other local functions  */
  80. void     main       _((int, char **));
  81. int      dofun      _((void));
  82. int      funcload   _((void));
  83. ads_real rfact      _((int x));
  84. ads_real rsqr       _((ads_real x));
  85.  
  86.  
  87. /*-----------------------------------------------------------------------*/
  88. /* MAIN - the main routine */
  89.  
  90. void main(argc,argv)
  91.   int argc;
  92.   char *argv[];
  93. {
  94.     short scode = RSRSLT;             /* Normal result code (default) */
  95.     int stat;
  96.     char errmsg[80];
  97.  
  98.     ads_init(argc, argv);             /* Open communication with AutoLISP */
  99.  
  100.     for ( ;; ) {                      /* Request/Result loop */
  101.  
  102.         if ((stat = ads_link(scode)) < 0) {
  103.             sprintf(errmsg, /*MSG1*/"FACT: bad status from ads_link() = %d\n",
  104.                     stat);
  105. #ifdef Macintosh
  106.             macalert(errmsg);
  107. #else
  108.             puts(errmsg);
  109.             fflush(stdout);
  110. #endif /* Macintosh */
  111.             exit(1);
  112.         }
  113.  
  114.         scode = RSRSLT;               /* Reset result code */
  115.  
  116.         switch (stat) {
  117.  
  118.         case RQXLOAD:                 /* Load & define functions */
  119.             scode = funcload() == RTNORM ? RSRSLT : RSERR;
  120.             break;
  121.  
  122.         case RQSUBR:                  /* Handle external function requests */
  123.             scode = dofun() == RTNORM ? RSRSLT : RSERR;
  124.             break;
  125.  
  126.         default:
  127.             break;
  128.         }
  129.     }
  130. }
  131.  
  132. /*-----------------------------------------------------------------------*/
  133. /* FUNCLOAD  --  Define this application's external functions.  Return
  134.                  RTERROR on error, else RTNORM.                   */
  135.  
  136. static int funcload()
  137. {
  138.     int i;
  139.  
  140.     for (i = 0; i < ELEMENTS(func_table); i++) {
  141.         if (!ads_defun(func_table[i].func_name, i))
  142.             return RTERROR;
  143.     }
  144.     return RTNORM;
  145. }
  146.  
  147. /*-----------------------------------------------------------------------*/
  148. /* DOFUN -- Execute external function (called upon an RQSUBR request).  
  149.             Return value from the function executed, RTNORM or RTERROR. */
  150.  
  151. static int dofun()
  152. {
  153.     struct resbuf *rb;
  154.     int val;
  155.  
  156.     /* Get the function code and check that it's within range.
  157.        (It can't fail to be, but paranoia doesn't hurt.) */
  158.     if ((val = ads_getfuncode()) < 0 || val >= ELEMENTS(func_table)) {
  159.         ads_fail(/*MSG2*/"Received nonexistent function code.");
  160.         return RTERROR;
  161.     }
  162.  
  163.     /* Fetch the arguments, if any. */
  164.     rb = ads_getargs();
  165.  
  166.     /* Call the handler and return its success-failure status. */
  167.     val = (*func_table[val].func)(rb);
  168.     ads_relrb(rb);
  169.     return val;
  170. }
  171.  
  172.  
  173. /* The code from the beginning of main() to here is UNCHANGED when you add or
  174.    delete functions.  */
  175.  
  176. /*-----------------------------------------------------------------------*/
  177. /* FACT -- First set up the argument, then call the factorial function */
  178. static int
  179. fact(rb)
  180.   struct resbuf *rb;
  181. {
  182.     int x;
  183.  
  184.     if (rb == NULL)
  185.         return RTERROR;
  186.  
  187.     if (rb->restype == RTSHORT) {
  188.         x = rb->resval.rint;          /* Save in local variable */
  189.     } else {
  190.         ads_fail(/*MSG3*/"Argument should be an integer.");
  191.         return RTERROR;
  192.     }
  193.  
  194.     if (x < 0) {                      /* Check argument range */
  195.         ads_fail(/*MSG4*/"Argument should be positive.");
  196.         return RTERROR;
  197.     } else if (x > 170) {             /* Avoid floating-point overflow */
  198.         ads_fail(/*MSG5*/"Argument should be 170 or less.");
  199.         return RTERROR;
  200.     }
  201.  
  202.     ads_retreal(rfact(x));            /* Call the function itself, and
  203.                                          return the value to AutoLISP */
  204.     return RTNORM;
  205. }
  206.  
  207. /*-----------------------------------------------------------------------*/
  208. /* This is the implementation of the actual external factorial function */
  209.  
  210. static ads_real rfact(n)
  211.   int n;
  212. {
  213.     ads_real ans = 1.0;
  214.  
  215.     while (n)
  216.         ans *= n--;
  217.  
  218.     return ans;
  219. }
  220.  
  221. /*-----------------------------------------------------------------------*/
  222. /* SQUAREROOT -- First set up the argument, then call the root function */
  223. static int
  224. squareroot(rb)
  225.   struct resbuf *rb;
  226. {
  227.     ads_real x;
  228.  
  229.     if (rb == NULL)
  230.         return RTERROR;               /* A proper error msg would be better */
  231.  
  232.     if (rb->restype == RTSHORT) {     /* Save in local variable */
  233.         x = (ads_real) rb->resval.rint;
  234.     } else if (rb->restype == RTREAL) {
  235.         x = rb->resval.rreal;         /* Can accept either real
  236.                                          or integer */
  237.     } else {
  238.         ads_fail(/*MSG6*/"Argument should be a real or integer value.");
  239.         return RTERROR;
  240.     }
  241.  
  242.     if (x < 0) {                      /* Check argument range */
  243.         ads_fail(/*MSG7*/"Argument should be positive.");
  244.         return RTERROR;
  245.     }
  246.  
  247.     ads_retreal(rsqr(x));             /* Call the function itself, and
  248.                                          return the value to AutoLISP */
  249.  
  250.     return RTNORM;
  251. }
  252.  
  253. /*-----------------------------------------------------------------------*/
  254. /* This is the implementation of the actual external function */
  255.  
  256. static ads_real rsqr(x)               /* Square root by Newton's method */
  257.   ads_real x;
  258. {
  259.     int n = 50;
  260.     ads_real y, c, cl;
  261.  
  262.     if (x == 0.0) {
  263.         return 0.0;
  264.     }
  265.  
  266.     y = (x * 2 + .1) / (x + 1.0);
  267.     c = (y - x / y) / 2;
  268.     cl= 0.0;
  269.  
  270.     while ((c != cl) && (n-- > 0)) {
  271.         y -= c;
  272.         cl = c;
  273.         c  = (y - x / y) / 2;
  274.     }
  275.     return y;
  276. }
  277.